1 package edu.jiangxin.apktoolbox.file.password.recovery.category.bruteforce; 2 3 import edu.jiangxin.apktoolbox.file.password.recovery.RecoveryPanel; 4 import edu.jiangxin.apktoolbox.file.password.recovery.State; 5 import edu.jiangxin.apktoolbox.file.password.recovery.category.ICategory; 6 import edu.jiangxin.apktoolbox.file.password.recovery.checker.FileChecker; 7 import edu.jiangxin.apktoolbox.file.password.recovery.checker.IChecker; 8 import org.apache.commons.lang3.StringUtils; 9 import org.apache.logging.log4j.LogManager; 10 import org.apache.logging.log4j.Logger; 11 12 import javax.swing.*; 13 import java.util.concurrent.ExecutorService; 14 import java.util.concurrent.Executors; 15 import java.util.concurrent.TimeUnit; 16 17 public class BruteForceProxy implements ICategory { 18 private static final Logger logger = LogManager.getLogger(BruteForceProxy.class.getSimpleName()); 19 20 private ExecutorService executorService; 21 22 private BruteForceFuture bruteForceFuture; 23 24 private static class BruteForceProxyHolder { 25 private static final BruteForceProxy instance = new BruteForceProxy(); 26 } 27 28 private BruteForceProxy() { 29 } 30 31 public static BruteForceProxy getInstance() { 32 return BruteForceProxyHolder.instance; 33 } 34 35 private String startAndGet(int numThreads, int passwordLength, IChecker checker, String charsSet, RecoveryPanel panel) { 36 executorService = Executors.newFixedThreadPool(numThreads); 37 bruteForceFuture = new BruteForceFuture(numThreads); 38 BruteForceTaskParam param = new BruteForceTaskParam(numThreads, passwordLength, checker, charsSet); 39 for (int taskId = 0; taskId < numThreads; taskId++) { 40 BruteForceRunnable task = new BruteForceRunnable(taskId, param, bruteForceFuture, panel); 41 executorService.execute(task); 42 } 43 String password = null; 44 try { 45 password = bruteForceFuture.get(); 46 } catch (Exception e) { 47 logger.info("Exception test: ", e); 48 } finally { 49 if (executorService.isShutdown()) { 50 executorService.shutdown(); 51 } 52 } 53 return password; 54 } 55 56 @Override 57 public void start(RecoveryPanel panel) { 58 String charset = panel.getCharset(); 59 logger.info("Charset: {}", charset); 60 if (StringUtils.isEmpty(charset)) { 61 JOptionPane.showMessageDialog(panel, "Character set is empty!"); 62 return; 63 } 64 65 int minLength = panel.getMinLength(); 66 int maxLength = panel.getMaxLength(); 67 if (minLength > maxLength) { 68 JOptionPane.showMessageDialog(panel, "Minimum length is bigger than maximum length!"); 69 return; 70 } 71 String password = null; 72 int totalNumber = 0; 73 for (int length = minLength; length <= maxLength; length++) { 74 totalNumber += (int)Math.pow(charset.length(), length); 75 } 76 panel.resetProgressMaxValue(totalNumber); 77 for (int length = minLength; length <= maxLength; length++) { 78 long startTime = System.currentTimeMillis(); 79 FileChecker fileChecker = panel.getCurrentFileChecker(); 80 int processorCount = Runtime.getRuntime().availableProcessors(); 81 int numThreads = getThreadCount(charset.length(), length, processorCount); 82 logger.info("[{}]Current attempt length: {}, thread number: {}", fileChecker, length, numThreads); 83 password = startAndGet(numThreads, length, fileChecker, charset, panel); 84 long endTime = System.currentTimeMillis(); 85 logger.info("Current attempt length: {}, Cost time: {}ms", length, (endTime - startTime)); 86 if (password != null || panel.getCurrentState() != State.WORKING) { 87 logger.info("Break state: {}", panel.getCurrentState()); 88 break; 89 } 90 } 91 panel.showResultWithDialog(password); 92 } 93 94 @Override 95 public void cancel() { 96 if (bruteForceFuture != null) { 97 bruteForceFuture.cancel(false); 98 } 99 if (executorService != null && !executorService.isShutdown()) { 100 executorService.shutdown(); 101 } 102 while (executorService != null && !executorService.isTerminated()) { 103 try { 104 final boolean isTimeout = !executorService.awaitTermination(100, TimeUnit.SECONDS); 105 logger.info("awaitTermination isTimeout: " + isTimeout); 106 } catch (InterruptedException e) { 107 logger.error("awaitTermination InterruptedException"); 108 Thread.currentThread().interrupt(); 109 } 110 } 111 } 112 113 private int getThreadCount(int charSetSize, int length, int maxThreadCount) { 114 int result = 1; 115 for (int i = 1; i <= length; i++) { 116 result *= charSetSize; 117 if (result >= maxThreadCount) { 118 return maxThreadCount; 119 } 120 } 121 return result; 122 } 123 }